package com.dbflow5.query;

import com.dbflow5.StringUtils;
import com.dbflow5.config.FlowManager;
import com.dbflow5.query.property.IProperty;
import com.dbflow5.sql.Query;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Description: Describes the method that the trigger uses.
 */
public class TriggerMethod<TModel> implements Query {
    Trigger trigger;
    private final String methodName;
    Class<TModel> onTable;

    private List<IProperty<?>> properties  = new ArrayList<>();
    private boolean forEachRow = false;
    private SQLOperator whenCondition = null;

    public TriggerMethod(Trigger trigger, String methodName, Class<TModel> onTable, IProperty<?>... properties){
        this.trigger = trigger;
        this.methodName = methodName;
        this.onTable = onTable;

        init(properties);
    }

    private void init(IProperty<?>... properties){
        if(properties == null){
            return;
        }
        List<IProperty<?>> list = Arrays.asList(properties);
        if (list.size() > 0 && list.get(0) != null) {
            if (!methodName.equals(UPDATE)) {
                throw new IllegalArgumentException("An Trigger OF can only be used with an UPDATE method");
            }
            this.properties = list;
        }
    }

    @Override
    public String getQuery() {
        StringBuilder queryBuilder = new StringBuilder(trigger.getQuery());
        queryBuilder.append(methodName);
        if (!properties.isEmpty()) {
            queryBuilder.append(" OF ");
            StringUtils.appendArray(queryBuilder, properties);
        }
        queryBuilder.append(" ON ").append(FlowManager.getTableName(onTable));

        if (forEachRow) {
            queryBuilder.append(" FOR EACH ROW ");
        }

        if(whenCondition != null){
            queryBuilder.append(" WHEN ");
            whenCondition.appendConditionToQuery(queryBuilder);
            queryBuilder.append(" ");
        }

        queryBuilder.append(" ");

        return queryBuilder.toString();
    }

    public TriggerMethod<TModel> forEachRow() {
        forEachRow = true;
        return this;
    }

    /**
     * Appends a WHEN condition after the ON name and before BEGIN...END
     *
     * @param condition The condition for the trigger
     * @return this
     */
    public TriggerMethod<TModel> when(SQLOperator condition) {
        whenCondition = condition;
        return this;
    }

    /**
     * Specify the logic that gets executed for this trigger. Supported statements include:
     * [Update], INSERT, [Delete],
     * and [Select]
     *
     * @param triggerLogicQuery The query to run for the BEGIN..END of the trigger
     * @return This trigger
     */
    public CompletedTrigger<TModel> begin(Query triggerLogicQuery) {
        return new CompletedTrigger<>(this, triggerLogicQuery);
    }

    public static final String DELETE = "DELETE";
    public static final String INSERT = "INSERT";
    public static final String UPDATE = "UPDATE";

    public static final List<String> METHODS = Arrays.asList(INSERT, UPDATE, DELETE);
}
